package com.rongshu.view.web;

import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.annotation.RequiresApi;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.webkit.DownloadListener;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.rongshu.R;
import com.rongshu.utils.Constant;
import com.rongshu.view.base.BaseActivity;
import com.utils.permissions.OnPermission;
import com.utils.permissions.XXPermissions;
import com.yalantis.ucrop.util.FileUtils;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import butterknife.BindView;
import butterknife.OnClick;

/**
 * created by zhengweis on 2019/1/3.
 * description：通用加载html页面
 */
public class ActivityWeb extends BaseActivity {
    @BindView(R.id.head_left)
    RelativeLayout headLeft;
    @BindView(R.id.head_middle)
    TextView headMiddle;
    @BindView(R.id.web)
    WebView web;
    @BindView(R.id.base_content_)
    LinearLayout baseContent;
    @BindView(R.id.load_fail_layout)
    RelativeLayout loadFailLayout;
    protected int loadUrlTimeout = 20 * 1000;
    private Timer timer;
    String title;
    String url;
    private boolean isShowloading = false;
    private UploadHandler mUploadHandler;
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);
            switch (msg.what) {
                case 1:
                    if (web.getProgress() < 50) {
                        web.stopLoading();
                        loadFailLayout.setVisibility(View.VISIBLE);
                    }
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected int initLayout() {
        return R.layout.activity_web_layout;
    }

    @Override
    protected void initView() {
        hintTitleBar();
        Intent inEntry = getIntent();
        if (inEntry != null) {
            //获取意图数据
            url = getIntent().getStringExtra(Constant.INTENT_H5);
            title = getIntent().getStringExtra(Constant.INTENT_TITLE);
        }
        init();
    }

    @Override
    protected void initData() {

    }

    @Override
    protected void updateViews(boolean isRefresh) {

    }

    @OnClick(R.id.head_left)
    public void onViewClicked() {
        showKeyboard(false);
        if (web != null && web.canGoBack()) {
            web.goBack();
        } else {
            onBackPressed();
        }
    }

    @Override
    public void onBackPressed() {
        setResult(RESULT_OK);
        super.onBackPressed();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && web.canGoBack()) {
            web.goBack();// 返回前一个页面
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onResume() {
        super.onResume();
        showLoading(false);
    }

    @Override
    protected void onDestroy() {
        if (web != null) {
            ViewGroup parent = (ViewGroup) web.getParent();
            if (parent != null) {
                parent.removeView(web);
            }
            web.clearCache(true);
            web.removeAllViews();
            web.pauseTimers();
            web.destroy();
        }
        if (timer != null) {
            timer.cancel();
            timer.purge();
            timer = null;
        }

        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
            mHandler = null;
        }
        web = null;
        super.onDestroy();
    }

    private void init() {
        if (!TextUtils.isEmpty(title)) {
            headMiddle.setText(title);
        }
        loadFailLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                web.reload();
                loadFailLayout.setVisibility(View.GONE);
            }
        });
        WebSettings settings = web.getSettings();
        web.setDownloadListener(new MyWebViewDownLoadListener());
        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
        settings.setBlockNetworkImage(false);
        settings.setUseWideViewPort(true);
        settings.setBuiltInZoomControls(false);
        settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        settings.setSupportMultipleWindows(true);
        settings.setAllowFileAccess(true);
        settings.setAppCacheEnabled(false);
        settings.setJavaScriptEnabled(true);
        settings.setJavaScriptCanOpenWindowsAutomatically(true);
        settings.setGeolocationEnabled(true);
        // 开启定位
        settings.setDomStorageEnabled(true);
        web.addJavascriptInterface(new JavaScriptObject(this), "app");
        web.setWebViewClient(new MywebViewClient(this));
        web.setWebChromeClient(webchromeClient);
        web.loadUrl(url);
    }

    private class MyWebViewDownLoadListener implements DownloadListener {

        @Override
        public void onDownloadStart(String url, String userAgent,
                                    String contentDisposition, String mimetype, long contentLength) {

        }
    }

    private final class MywebViewClient extends WebViewClient {

        private Context weakReference;

        public MywebViewClient(Context context) {
            weakReference = context;
        }

        @Override
        public void onPageStarted(final WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            if (timer == null) {
                timer = new Timer();
            }
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    Message msg = Message.obtain();
                    msg.what = 1;
                    if (mHandler != null) {
                        mHandler.sendMessage(msg);
                    }
                }
            }, loadUrlTimeout);
        }

        // 文件找不到，网络连不上，服务器找不到等问题
        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                return;
            }
            loadFailLayout.setVisibility(View.VISIBLE);
            super.onReceivedError(view, errorCode, description, failingUrl);
        }

        // 新版本，只会在Android6及以上调用
        @TargetApi(Build.VERSION_CODES.M)
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            if (request != null && request.isForMainFrame()) { // 或者： if(request.getUrl().toString() .equals(getUrl()))
                loadFailLayout.setVisibility(View.VISIBLE);
            }

            super.onReceivedError(view, request, error);
        }

        //http errors
        @Override
        public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
//            loadFailLayout.setVisibility(View.VISIBLE);
            super.onReceivedHttpError(view, request, errorResponse);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (timer != null) {
                timer.cancel();
                timer.purge();
                timer = null;
            }
            if (mHandler != null) {
                mHandler.removeCallbacksAndMessages(null);
                mHandler = null;
            }
        }

        @RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // TODO: 2019/1/3 交互
//            if (url.startsWith("****")) {
//
//            }
            return super.shouldOverrideUrlLoading(view, url);
        }
    }

    /**
     * 负责文件选择和回调处理
     */
    class UploadHandler {
        private String mCameraFilePath;
        private boolean mCaughtActivityNotFoundException;
        private Controller mController;
        private ValueCallback mUploadMessage;

        public UploadHandler(Controller controller) {
            mController = controller;
        }

        public void onResult(int resultCode, Intent intent) {
            if (resultCode == Activity.RESULT_CANCELED && mCaughtActivityNotFoundException) {
                // Couldn't resolve an activity, we are going to try again so skip
                // this result.
                mCaughtActivityNotFoundException = false;
                return;
            }

            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { //5.0以下版本
                try {
                    Uri result = ((intent == null) || (resultCode != RESULT_OK)) ? null : intent.getData();
                    if (result == null && intent == null && resultCode == Activity.RESULT_OK) {  //相机
                        File cameraFile = new File(mCameraFilePath);
                        if (cameraFile.exists()) {
                            result = Uri.fromFile(cameraFile);
                            // Broadcast to the media scanner that we have a new photo
                            // so it will be added into the gallery for the user.
                            mController.getActivity().sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
                        }
                    } else if (result != null) { //文档
                        String path = FileUtils.getPath(ActivityWeb.this, result);
                        result = Uri.fromFile(new File(path));
                    }
                    mUploadMessage.onReceiveValue(result);
                    mUploadMessage = null;
                    mCaughtActivityNotFoundException = false;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else { //5.0以上版本
                try {
                    Uri[] results = null;
                    if (intent == null && resultCode == Activity.RESULT_OK) {  //相机
                        File cameraFile = new File(mCameraFilePath);
                        if (cameraFile.exists()) {
                            Uri result = Uri.fromFile(cameraFile);
                            results = new Uri[]{result};
                            // Broadcast to the media scanner that we have a new photo
                            // so it will be added into the gallery for the user.
                            mController.getActivity().sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
                        }
                    } else if (intent != null) {  //文档
                        String dataString = intent.getDataString();
                        ClipData clipData = intent.getClipData();
                        if (clipData != null) {
                            int itemCount = clipData.getItemCount();
                            results = new Uri[itemCount];
                            for (int i = 0; i < itemCount; i++) {
                                ClipData.Item item = clipData.getItemAt(i);
                                results[i] = item.getUri();
                            }
                        }
                        if (dataString != null) {
                            results = new Uri[]{Uri.parse(dataString)};
                        }
                    }
                    mUploadMessage.onReceiveValue(results);
                    mUploadMessage = null;
                    mCaughtActivityNotFoundException = false;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
            final String imageMimeType = "image/*";
            final String videoMimeType = "video/*";
            final String audioMimeType = "audio/*";
            if (mUploadMessage != null) {
                // Already a file picker operation in progress.
                return;
            }
            mUploadMessage = uploadMsg;
            // Parse the accept type.
            String params[] = acceptType.split(";");
            String mimeType = params[0];
            //Ensure it is not still set from a previous upload.
            mCameraFilePath = null;
            if (mimeType.equals(imageMimeType)) {
                //boolean
                if (!XXPermissions.isHasPermission(ActivityWeb.this, Manifest.permission.CAMERA)) {
                    XXPermissions.with(ActivityWeb.this).permission(Manifest.permission.CAMERA).request(new OnPermission() {
                        @Override
                        public void hasPermission(List<String> granted, boolean isAll) {
                            selectImage(imageMimeType);
                        }

                        @Override
                        public void noPermission(List<String> denied, boolean quick) {

                        }
                    });
                } else {
                    selectImage(imageMimeType);
                }
                return;
            } else {
                startActivity(createDefaultOpenableIntent());
            }
            //// TODO: 2017/10/16 摄像、录音功能暂时不开通，后期需要再扩展
//            if (mimeType.equals(videoMimeType)) {
//                Intent chooser = createChooserIntent(createCamcorderIntent());
//                chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(videoMimeType));
//                startActivity(chooser);
//                return;
//            } else if (mimeType.equals(audioMimeType)) {
//                Intent chooser = createChooserIntent(createSoundRecorderIntent());
//                chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(audioMimeType));
//                startActivity(chooser);
//                return;
//            }
            // No special handling based on the accept type was necessary, so trigger the default
            // file upload chooser.
//            startActivity(createDefaultOpenableIntent());
        }

        private void selectImage(String imageMimeType) {
            Intent chooser = createChooserIntent(createCameraIntent());
            chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(imageMimeType));
            startActivity(chooser);
        }

        private void startActivity(Intent intent) {
            try {
                mController.getActivity().startActivityForResult(intent, Controller.FILE_SELECTED);
            } catch (ActivityNotFoundException e) {
                // No installed app was able to handle the intent that
                // we sent, so fallback to the default file upload control.
                try {
                    mCaughtActivityNotFoundException = true;
                    mController.getActivity().startActivityForResult(createDefaultOpenableIntent(),
                            Controller.FILE_SELECTED);
                } catch (ActivityNotFoundException e2) {
                    // Nothing can return us a file, so file upload is effectively disabled.
                    Toast.makeText(mController.getActivity(), "File uploads are disabled.", Toast.LENGTH_LONG).show();
                }
            }
        }

        /**
         * 默认文件选择方式，目前是相机和文档
         */
        private Intent createDefaultOpenableIntent() {
            Intent chooser = createChooserIntent(createCameraIntent());
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            chooser.putExtra(Intent.EXTRA_INTENT, i);
            return chooser;
        }

        private Intent createChooserIntent(Intent... intents) {
            Intent chooser = new Intent(Intent.ACTION_CHOOSER);
            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
            return chooser;
        }

        private Intent createOpenableIntent(String type) {
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType(type);
            return i;
        }

        public static final String FILE_PATH = "user";

        /**
         * 创建相机、文档文件选择器
         */
        private Intent createCameraIntent() {
            Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            File file = getExternalFilesDir(FILE_PATH);// Environment.getExternalStorageDirectory()
            // + FILE_PATH;
            if (file != null) {
                String path = file.getPath();
                if (path != null && makeDir(path)) {
                    String str = new Date().getTime() + ".jpg";// new
                    mCameraFilePath = path + "/" + str;
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(ActivityWeb.this, getPackageName() + ".provider", new File(path, str)));
                    } else {
                        Uri imageUri = Uri.fromFile(new File(path, str));
                        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                    }
                }
            }
            return cameraIntent;
        }

        /**
         * 新建文件夹
         */
        private boolean makeDir(String path) {
            if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                return false;
            }
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            return true;
        }

        /**
         * 创建摄像机
         */
        private Intent createCamcorderIntent() {
            return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        }

        /**
         * 创建录音机
         */
        private Intent createSoundRecorderIntent() {
            return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
        }
    }

    class Controller {

        final static int FILE_SELECTED = 4;

        Activity getActivity() {
            return ActivityWeb.this;
        }
    }

    /***
     * 网页加载进度和文件选择器
     */
    WebChromeClient webchromeClient = new WebChromeClient() {
        public void onProgressChanged(WebView view, int progress) {
            if (progress != 100) {
                if (!isShowloading) {
                    isShowloading = true;
                    showLoading(true);
                }
            } else {
                isShowloading = false;
                showLoading(false);
            }
        }
        // For Android TARGET 2.x  版本

        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            openFileChooser(uploadMsg, "");
        }

        // For Android TARGET3.x  版本
        public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
            mUploadHandler = new UploadHandler(new Controller());
            mUploadHandler.openFileChooser(uploadMsg, acceptType);
        }

        // For Android 4.x target 版本
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            openFileChooser(uploadMsg, acceptType);
        }

        // For Android 5.x target 版本
        @SuppressLint("NewApi")
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
            String acceptType = "*/*";
            if (fileChooserParams != null && fileChooserParams.getAcceptTypes() != null
                    && fileChooserParams.getAcceptTypes().length > 0) {
                acceptType = fileChooserParams.getAcceptTypes()[0];
            }
            openFileChooser(filePathCallback, acceptType);
            return true;
        }

        /*** 视频播放相关的方法 **/

        @Override
        public View getVideoLoadingProgressView() {
            FrameLayout frameLayout = new FrameLayout(ActivityWeb.this);
            frameLayout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
            return frameLayout;
        }

        @Override
        public void onShowCustomView(View view, CustomViewCallback callback) {
            showCustomView(view, callback);
        }

        @Override
        public void onHideCustomView() {
            hideCustomView();
        }
    };
    private View customView;
    private FrameLayout fullscreenContainer;
    private WebChromeClient.CustomViewCallback mCallback;
    /**
     * 视频全屏参数
     */
    protected static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS =
            new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

    /**
     * 视频播放全屏
     **/
    private void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
        // if a view already exists then immediately terminate the new one
        if (customView != null) {
            callback.onCustomViewHidden();
            return;
        }
        fullScreen();
        getWindow().getDecorView();
        FrameLayout decor = (FrameLayout) getWindow().getDecorView();
        fullscreenContainer = new FullscreenHolder(ActivityWeb.this);
        fullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
        decor.addView(fullscreenContainer, COVER_SCREEN_PARAMS);
        customView = view;
        setStatusBarVisibility(false);
        mCallback = callback;
        web.setVisibility(View.GONE);
    }

    /**
     * 隐藏视频全屏
     */
    private void hideCustomView() {
        if (customView == null) {
            return;
        }
        fullScreen();
        setStatusBarVisibility(true);
        FrameLayout decor = (FrameLayout) getWindow().getDecorView();
        decor.removeView(fullscreenContainer);
        fullscreenContainer = null;
        customView = null;
        mCallback.onCustomViewHidden();
        web.setVisibility(View.VISIBLE);
    }

    /**
     * 全屏容器界面
     */
    static class FullscreenHolder extends FrameLayout {

        public FullscreenHolder(Context ctx) {
            super(ctx);
            setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
        }

        @Override
        public boolean onTouchEvent(MotionEvent evt) {
            return true;
        }
    }

    private void setStatusBarVisibility(boolean visible) {
        int flag = visible ? 0 : WindowManager.LayoutParams.FLAG_FULLSCREEN;
        getWindow().setFlags(flag, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

    private void fullScreen() {
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }

}
